/*
PureMVC AS3 Utility - StateMachine
Copyright (c) 2008 Neil Manuell, Cliff Hall
Your reuse is governed by the Creative Commons Attribution 3.0 License
*/
package uk.co.revisual.domino.injectors
{
	import org.puremvc.as3.multicore.patterns.observer.Notifier;
	import org.puremvc.as3.multicore.utilities.statemachine.FSMInjector;
	import org.puremvc.as3.multicore.utilities.statemachine.State;
	import org.puremvc.as3.multicore.utilities.statemachine.StateMachine;
	
	import uk.co.revisual.creation.Creatable;
	import uk.co.revisual.domino.consts.DominoConsts;
	import uk.co.revisual.utils.xml.getPathsFromXML_URI;
	
	/**
	 * Creates and registers a StateMachine described in XML.
	 * 
	 * <P>
	 * This allows reconfiguration of the StateMachine 
	 * without changing any code, as well as making it 
	 * easier than creating all the <code>State</code> 
	 * instances and registering them with the 
	 * <code>StateMachine</code> at startup time.
	 * 
	 * @ see State
	 * @ see StateMachine
	 */
	public class CustomClassFSMInjector extends FSMInjector
	{
		/**
		 * Constructor.
		 */
		public function CustomClassFSMInjector( fsm:XML, factory:Creatable ) 
		{
			this.factory = factory;
			super(fsm);
		}
		
		/**
		 * Creates a <code>State</code> instance from its XML definition.
		 */
		override protected function createState( stateDef:XML ):State
		{
			// Create State object
			var name:String = stateDef.@name.toString();
			var exiting:String = stateDef.@exiting.toString();
			var entering:String = stateDef.@entering.toString();
			var changed:String = stateDef.@changed.toString();
			var classpath:String = getClassPath( stateDef );
			var state:State = getState(classpath, name, entering, exiting, changed );
			//var state:State = new State( name, entering, exiting, changed );
			
			// Create transitions
			var transitions:XMLList = stateDef..transition as XMLList;
			for (var i:int; i<transitions.length(); i++)
			{
				var transDef:XML = transitions[i];
				state.defineTrans( String(transDef.@action), String(transDef.@target) );
			}
			return state;
		}
		
		protected function getClassPath( stateDef:XML ):String{
			var results:Array = getPathsFromXML_URI( stateDef,  DominoConsts.ATTRIBUTE_LOCAL_NAMES.CLASS );
			return String( results[0] );
		}
		
		protected function getState( path:String, name:String, entering:String, exiting:String, changed:String ):State{
			if(path == "undefined") return new State( name, entering, exiting, changed );
			var c:Class = Class( factory.create( path, true ) );
			var state:State = new c( name, entering, exiting, changed );
			return state;
		}
	
		// The class factory 
		protected var factory:Creatable;
	}
}